home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / elvis172.zip / elvprsv.c < prev    next >
C/C++ Source or Header  |  1993-03-28  |  8KB  |  314 lines

  1. /* elvprsv.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the portable sources for the "elvprsv" program.
  12.  * "Elvprsv" is run by Elvis when Elvis is about to die.  It is also
  13.  * run when the computer boots up.  It is not intended to be run directly
  14.  * by the user, ever.
  15.  *
  16.  * Basically, this program does the following four things:
  17.  *    - It extracts the text from the temporary file, and places the text in
  18.  *    a file in the /usr/preserve directory.
  19.  *    - It adds a line to the /usr/preserve/Index file, describing the file
  20.  *    that it just preserved.
  21.  *    - It removes the temporary file.
  22.  *    -    It sends mail to the owner of the file, saying that the file was
  23.  *    preserved, and how it can be recovered.
  24.  *
  25.  * The /usr/preserve/Index file is a log file that contains one line for each
  26.  * file that has ever been preserved.  Each line of this file describes one
  27.  * preserved file.  The first word on the line is the name of the file that
  28.  * contains the preserved text.  The second word is the full pathname of the
  29.  * file that was being edited; for anonymous buffers, this is the directory
  30.  * name plus "/foo".
  31.  *
  32.  * If elvprsv's first argument (after the command name) starts with a hyphen,
  33.  * then the characters after the hyphen are used as a description of when
  34.  * the editor went away.  This is optional.
  35.  *
  36.  * The remaining arguments are all the names of temporary files that are
  37.  * to be preserved.  For example, on a UNIX system, the /etc/rc file might
  38.  * invoke it this way:
  39.  *
  40.  *    elvprsv "-the system went down" /tmp/elv_*.*
  41.  *
  42.  * This file contains only the portable parts of the preserve program.
  43.  * It must #include a system-specific file.  The system-specific file is
  44.  * expected to define the following functions:
  45.  *
  46.  *    char *ownername(char *filename)    - returns name of person who owns file
  47.  *
  48.  *    void mail(char *user, char *name, char *when)
  49.  *                    - tell user that file was preserved
  50.  */
  51.  
  52. #include <stdio.h>
  53. #include "config.h"
  54. #include "vi.h"
  55.  
  56. /* We include ctype.c here (instead of including just ctype.h and linking
  57.  * with ctype.o) because on some systems ctype.o will have been compiled in
  58.  * "large model" and the elvprsv program is to be compiled in "small model" 
  59.  * You can't mix models.  By including ctype.c here, we can avoid linking
  60.  * with ctype.o.
  61.  */
  62. #include "ctype.c"
  63.  
  64. void preserve P_((char *, char *));
  65. void main P_((int, char **));
  66.  
  67. #if AMIGA
  68. BLK tmpblk;
  69. # include "amiwild.c"
  70. # include "amiprsv.c"
  71. #endif
  72.  
  73. #if OSK
  74. # undef sprintf
  75. #endif
  76.  
  77. #if ANY_UNIX || OSK
  78. # include "prsvunix.c"
  79. #endif
  80.  
  81. #if MSDOS || TOS || OS2
  82. # include "prsvdos.c"
  83. # define WILDCARD_NO_MAIN
  84. # include "wildcard.c"
  85. #endif
  86.  
  87.  
  88. BLK    buf;
  89. BLK    hdr;
  90. BLK    name;
  91. int    rewrite_now;    /* boolean: should we send text directly to orig file? */
  92.  
  93.  
  94.  
  95. /* This function preserves a single file, and announces its success/failure
  96.  * via an e-mail message.
  97.  */
  98. void preserve(tname, when)
  99.     char    *tname;        /* name of a temp file to be preserved */
  100.     char    *when;        /* description of when the editor died */
  101. {
  102.     int    infd;        /* fd used for reading from the temp file */
  103.     FILE    *outfp;        /* fp used for writing to the recovery file */
  104.     FILE    *index;        /* fp used for appending to index file */
  105.     char    outname[100];    /* the name of the recovery file */
  106.     char    *user;        /* name of the owner of the temp file */
  107. #if AMIGA
  108.     char    *prsvdir;
  109. #endif
  110.     int    i;
  111.  
  112.     /* open the temp file */
  113.     infd = open(tname, O_RDONLY|O_BINARY);
  114.     if (infd < 0)
  115.     {
  116.         /* if we can't open the file, then we should assume that
  117.          * the filename contains wildcard characters that weren't
  118.          * expanded... and also assume that they weren't expanded
  119.          * because there are no files that need to be preserved.
  120.          * THEREFORE... we should silently ignore it.
  121.          * (Or loudly ignore it if the user was using -R)
  122.          */
  123.         if (rewrite_now)
  124.         {
  125.             perror(tname);
  126.         }
  127.         return;
  128.     }
  129.  
  130.     /* read the header and name from the file */
  131.     if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
  132.      || read(infd, name.c, BLKSIZE) != BLKSIZE)
  133.     {
  134.         /* something wrong with the file - sorry */
  135.         fprintf(stderr, "%s: truncated header blocks\n", tname);
  136.         close(infd);
  137.         return;
  138.     }
  139.  
  140.     /* If the filename block contains an empty string, then Elvis was
  141.      * only keeping the temp file around because it contained some text
  142.      * that was needed for a named cut buffer.  The user doesn't care
  143.      * about that kind of temp file, so we should silently delete it.
  144.      */
  145.     if (name.c[0] == '\0' && name.c[1] == '\177')
  146.     {
  147.         close(infd);
  148.         unlink(tname);
  149.         return;
  150.     }
  151.  
  152.     /* If there are no text blocks in the file, then we must've never
  153.      * really started editing.  Discard the file.
  154.      */
  155.     if (hdr.n[1] == 0)
  156.     {
  157.         close(infd);
  158.         unlink(tname);
  159.         return;
  160.     }
  161.  
  162.     if (rewrite_now)
  163.     {
  164.         /* we don't need to open the index file */
  165.         index = (FILE *)0;
  166.  
  167.         /* make sure we can read every block! */
  168.         for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
  169.         {
  170.             lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
  171.             if (read(infd, buf.c, BLKSIZE) != BLKSIZE
  172.              || buf.c[0] == '\0')
  173.             {
  174.                 /* messed up header */
  175.                 fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
  176.                 close(infd);
  177.                 return;
  178.             }
  179.         }
  180.  
  181.         /* open the user's file for writing */
  182.         outfp = fopen(name.c, "w");
  183.         if (!outfp)
  184.         {
  185.             perror(name.c);
  186.             close(infd);
  187.             return;
  188.         }
  189.     }
  190.     else
  191.     {
  192.         /* open/create the index file */
  193.         index = fopen(PRSVINDEX, "a");
  194.         if (!index)
  195.         {
  196.             perror(PRSVINDEX);
  197.             exit(2);
  198.         }
  199.  
  200.         /* should be at the end of the file already, but MAKE SURE */
  201.         fseek(index, 0L, 2);
  202.  
  203.         /* create the recovery file in the PRESVDIR directory */
  204. #if AMIGA
  205.         prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
  206.         if (*prsvdir == '/' || *prsvdir == ':')
  207.         {
  208.             sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
  209.         }
  210.         else
  211. #endif
  212.         sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
  213.         outfp = fopen(outname, "w");
  214.         if (!outfp)
  215.         {
  216.             perror(outname);
  217.             close(infd);
  218.             fclose(index);
  219.             return;
  220.         }
  221.     }
  222.  
  223.     /* write the text of the file out to the recovery file */
  224.     for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
  225.     {
  226.         lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
  227.         if (read(infd, buf.c, BLKSIZE) != BLKSIZE
  228.          || buf.c[0] == '\0')
  229.         {
  230.             /* messed up header */
  231.             fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
  232.             fclose(outfp);
  233.             close(infd);
  234.             if (index)
  235.             {
  236.                 fclose(index);
  237.             }
  238.             unlink(outname);
  239.             return;
  240.         }
  241.         fputs(buf.c, outfp);
  242.     }
  243.  
  244.     /* add a line to the index file */
  245.     if (index)
  246.     {
  247.         fprintf(index, "%s %s\n", outname, name.c);
  248.     }
  249.  
  250.     /* close everything */
  251.     close(infd);
  252.     fclose(outfp);
  253.     if (index)
  254.     {
  255.         fclose(index);
  256.     }
  257.  
  258.     /* Are we doing this due to something more frightening than just
  259.      * a ":preserve" command?
  260.      */
  261.     if (*when)
  262.     {
  263.         /* send a mail message */
  264.         mail(ownername(tname), name.c, when);
  265.  
  266.         /* remove the temp file -- the editor has died already */
  267.         unlink(tname);
  268.     }
  269. }
  270.  
  271. void main(argc, argv)
  272.     int    argc;
  273.     char    **argv;
  274. {
  275.     int    i;
  276.     char    *when = "the editor went away";
  277.  
  278. #if MSDOS || TOS || OS2
  279.     /* expand any wildcards in the command line */
  280.     _ct_init("");
  281.     argv = wildexpand(&argc, argv);
  282. #endif
  283.  
  284.     /* do we have a "-c", "-R", or "-when elvis died" argument? */
  285.     i = 1;
  286.     if (argc >= i + 1 && !strcmp(argv[i], "-R"))
  287.     {
  288.         rewrite_now = 1;
  289.         when = "";
  290.         i++;
  291. #if ANY_UNIX
  292.         setuid(geteuid());
  293. #endif
  294.     }
  295. #if OSK
  296.     else
  297.     {
  298.         setuid(0);
  299.     }
  300. #endif
  301.     if (argc >= i + 1 && argv[i][0] == '-')
  302.     {
  303.         when = argv[i] + 1;
  304.         i++;
  305.     }
  306.  
  307.     /* preserve everything we're supposed to */
  308.     while (i < argc)
  309.     {
  310.         preserve(argv[i], when);
  311.         i++;
  312.     }
  313. }
  314.